#include "renlian.h"
#include "ui_renlian.h"
#include "mainwindow.h"
renlian::renlian(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::renlian)
{
    ui->setupUi(this);
    //获得视频输入设备的链表,MediaDevices::videoInputs()获取系统的所有摄像头，并返回一个链表
    const QList<QCameraDevice> cameras = QMediaDevices::videoInputs();
    //遍历所有的摄像头设备
    for (const QCameraDevice &cameraDevice : cameras) {
        qDebug()<<cameraDevice.description();//打印摄像头的名字
        if(cameraDevice.description() == "HD Camera")
        {
            //创建一个摄像头，因为我电脑上只有一个，所以这里直接创建了。实际开发中一般会根据摄像头的名字来决定用哪个摄像头
            camera = new QCamera(cameraDevice);
            camera->start();//启动摄像头
            //QMediaCaptureSession对象可以把摄像头显示到指定QVedioWidget上
            pSession = new QMediaCaptureSession;
            pSession->setCamera(camera);//指定摄像头
            pSession->setVideoOutput(ui->widget_1);//指定要显示的窗口
            //图像截图工具
            imageCapture = new QImageCapture;
            pSession->setImageCapture(imageCapture);//设置图像截图工具，把截图工具给媒体捕获对象用
        }

    }
}

renlian::~renlian()
{
    delete ui;
}

void renlian::on_pushButton_clicked()
{
    imageCapture->captureToFile("d:/4.jpg");//截图
}



void renlian::on_pushButton_2_clicked()
{
    imageCapture->captureToFile("d:/5.jpg");//截图
    //图像截图工具
    // QImageCapture * imageCapture = new QImageCapture;
    // pSession->setImageCapture(imageCapture);//设置图像截图工具
    // imageCapture->captureToFile("d:/2.jpg");//截图

    _sleep(5000);//等待图片保存完成


    //得到了两张图片的字节编码，getFileBase64Content函数又百度提供源码
    QByteArray img = getFileBase64Content("d:/4.jpg", false).c_str();
    QByteArray img1 = getFileBase64Content("d:/5.jpg", false).c_str();
    qDebug()<<"+++++++++++++++++++++++";
    //创建了三个空的JSON对象
    cJSON *obj = cJSON_CreateObject();
    cJSON *obj1 = cJSON_CreateObject();
    cJSON *array = cJSON_CreateArray();

    // array:[obj:{
    //     "image";2.jpg的字符串编码;
    //     "image_type": BASE64;
    // },obj1:{
    //     "image";3.jpg的字符串编码;
    //     "image_type": BASE64;
    // }]


    //根据百度的要求和提供的函数，把图片加工成百度需要的编码格式
    cJSON_AddItemToObject(obj, "image", cJSON_CreateString(img.data()));//图片的数据
    cJSON_AddItemToObject(obj, "image_type", cJSON_CreateString("BASE64"));//数据的字节格式
    cJSON_AddItemToArray(array, obj);//使用百度提供的函数，把对象再打包成json数组

    cJSON_AddItemToObject(obj1, "image", cJSON_CreateString(img1.data()));
    cJSON_AddItemToObject(obj1, "image_type", cJSON_CreateString("BASE64"));
    cJSON_AddItemToArray(array, obj1);
    //此时数组里面包含了两张图片的信息，每张图片有两个key，分别是"image"和"image_type"


    const char *data = cJSON_Print(array);//把json数组转为JSON字符串

    //准备百度允许要的安全机制
    QSslSocket::supportsSsl();
    QSslSocket::sslLibraryBuildVersionString();

    QNetworkAccessManager manager;
    //在链接的=号后面加上百度云提供的token
    QNetworkRequest request(QUrl("https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=24.d94998068b3b8a9dcdc7d8081fc9767e.2592000.1750925581.282335-119046201"));
    //设置网页的请求头
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    //post函数把我们的数据投递到请求的网址（百度元）上去，并返回一个应答对象
    QNetworkReply *reply = manager.post(request, data);
    qDebug()<<"-------------------------";
    //循环等待百度云返回的数据
    QEventLoop loop;
    //把应答对象的应答结束信号和等待应答消息的循环退出函数绑定，也就是接收数据完成的时候就然循环等待结束
    connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    //启动循环等待
    loop.exec();

    //如果程序到了这里，说明百度已经给我们应答了
    if (reply->error() == QNetworkReply::NoError) {
        //把百度返回给我们字节全部读取出来
        QByteArray responseData = reply->readAll();
        qDebug()<<responseData;
        processBaiduFaceMatchResponse(responseData);
    } else {
        qDebug() << "HTTP 请求错误：" << reply->errorString();
    }

    reply->deleteLater();
}

void renlian::processBaiduFaceMatchResponse(const QByteArray &responseData)
{
    QJsonParseError error;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData, &error);

    if (error.error != QJsonParseError::NoError) {
        qDebug() << "JSON 解析错误：" << error.errorString();
    } else {
        qDebug() << responseData;
        if (jsonDoc.isObject()) {
            QJsonObject jsonObj = jsonDoc.object();
            if (jsonObj.contains("result"))
            {
                QJsonObject resultObj = jsonObj.value("result").toObject();
                if (resultObj.contains("score")) {
                    QJsonValue scoreValue = resultObj.value("score");
                    double score = scoreValue.toDouble();
                    qDebug() << "相似度：" << score;
                    if(score>80)
                    {
                        qDebug()<<"识别成功";
                        // QMessageBox::about(this,"提示","识别成功");
                        // music *p = new music;
                        // p->show();
                        // this->close();

                        MainWindow *p = new MainWindow;
                        p->data_1 = "31";
                        p->Openfan_1();
// qDebug()<<"识别成功241212412421423rwefergrtegtreg";
                    }
                    else
                    {
                        qDebug()<<"识别失败";
                        QMessageBox::about(this,"提示","识别失败");
                        this->close();
                        MainWindow *p = new MainWindow;
                        p->data_1 = "30";
                        // p->show();
                        p->ColseFan();

                    }
                    // ui->label_res->setText("相似度：" + QString::number(score));
                }
            }
        }
    }
}

//获得图片的base64格式的字节编码，因为百度云获取图片是通过这种编码来解析的
std::string renlian::getFileBase64Content(const char * path,  bool)
{
    const std::string base64_chars =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz"
        "0123456789+/";
    std::string ret;
    int i = 0;
    int j = 0;
    unsigned char char_array_3[3];
    unsigned char char_array_4[4];
    unsigned int bufferSize = 1024;
    unsigned char buffer[bufferSize];
    std::ifstream file_read;
    file_read.open(path, std::ios::binary);
    while (!file_read.eof())
    {
        file_read.read((char *) buffer, bufferSize * sizeof(char));
        int num = file_read.gcount();
        int m = 0;
        while (num--)
        {
            char_array_3[i++] = buffer[m++];
            if(i == 3)
            {
                char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
                char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
                char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
                char_array_4[3] = char_array_3[2] & 0x3f;
                for(i = 0; (i <4) ; i++)
                {
                    ret += base64_chars[char_array_4[i]];
                }
                i = 0;
            }
        }
    }
    file_read.close();
    if(i)
    {
        for(j = i; j < 3; j++)
        {
            char_array_3[j] = '\0';
        }

        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;
        for(j = 0; (j < i + 1); j++)
        {
            ret += base64_chars[char_array_4[j]];
        }
        while((i++ < 3))
        {
            ret += '=';
        }
    }

    return ret;
}

